package com.zcoj.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zcoj.core.model.ApiResponse;
import com.zcoj.core.model.PageData;
import com.zcoj.core.model.PageWrap;
import com.zcoj.mapper.*;
import com.zcoj.pojo.Dto.*;
import com.zcoj.pojo.Vo.*;
import com.zcoj.security.dto.LoginUser;
import com.zcoj.service.DiscussionService;
import com.zcoj.service.ProblemService;
import com.zcoj.service.UserService;
import com.zcoj.util.RedisCaches;
import com.zcoj.util.WrapperUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Service实现
 * @author 剩xia的盛夏
 * @date 2023/02/24 16:16
 */
@Service
public class DiscussionServiceImpl implements DiscussionService {

    @Autowired
    private DiscussionMapper discussionMapper;

    @Autowired
    private DiscussionLikeMapper discussionLikeMapper;

    @Autowired
    private RedisCaches redisCaches;


    @Autowired
    private DiscussionReportMapper discussionReportMapper;

    @Autowired
    private ReplyMapper replyMapper;

    @Autowired
    private ProblemService problemService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private CommentMapper commentMapper;

    @Override
    public ApiResponse create(Discussion discussion) {
        if(Objects.nonNull(discussion.getPid())){
           if( !problemService.isProblemValidID(discussion.getPid())){
               return ApiResponse.failed("题目ID不存");
           }
        }
        LoginUser loginUser = redisCaches.getLoginUser();
        User userServiceById = userService.findById(loginUser.getId());
        if(Objects.isNull(userServiceById)){
            return ApiResponse.failed("用户ID错误");
        }

        discussion.setFaceUrl(userServiceById.getFaceUrl());
        discussion.setAuthor(loginUser.getUsername());
        discussion.setUid(loginUser.getId());
        discussion.setRole(loginUser.getPermission().get(0));
        discussionMapper.insert(discussion);
        return discussion.getId()>0?ApiResponse.success("创建成功",null):ApiResponse.failed("创建失败");
    }

    @Override
    public Integer deleteById(Integer id) {
        return discussionMapper.deleteById(id);
    }

    @Override
    public void deleteByIdInBatch(List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) return;
        discussionMapper.deleteBatchIds(ids);
    }

    @Override
    public Integer updateById(Discussion discussion) {
        return discussionMapper.updateById(discussion);
    }

    @Override
    public void updateByIdInBatch(List<Discussion> discussions) {
        if (CollectionUtils.isEmpty(discussions)) return;
        for (Discussion discussion: discussions) {
            this.updateById(discussion);
        }
    }

    @Override
    public Discussion findById(Integer id) {
        return discussionMapper.selectById(id);
    }

    @Override
    public DiscussionVO findByIdVo(Integer id) {
        LoginUser loginUser = redisCaches.getLoginUser();
        Discussion discussion = discussionMapper.selectById(id);
        DiscussionVO discussionVO = new DiscussionVO();
        if(Objects.nonNull(loginUser)&&Objects.nonNull(id)&&Objects.nonNull(discussion)){
            discussionVO.setDiscussion(discussion);
            QueryWrapper<DiscussionLike> queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("uid",loginUser.getId()).eq("did",id);
            DiscussionLike discussionLike = discussionLikeMapper.selectOne(queryWrapper);
            if(Objects.nonNull(discussionLike)){
                discussionVO.setIsLike(1);
            }else {
                discussionVO.setIsLike(0);
            }
        }
        return discussionVO;
    }

    @Override
    public Discussion findOne(Discussion discussion) {
        Wrapper<Discussion> wrapper = new QueryWrapper<>(discussion);
        return discussionMapper.selectOne(wrapper);
    }

    @Override
    public Boolean clickLike(Integer id) {
        LoginUser loginUser = redisCaches.getLoginUser();
        if(Objects.nonNull(loginUser)&&Objects.nonNull(id)){
//            String discusssLikekey="discusssLikekey:"+String.valueOf(id);
//            String cacheObject = redisCaches.getCacheObject(discusssLikekey);
//            if(Objects.isNull(cacheObject)){
//                QueryWrapper<Discussion> discussionQueryWrapper=new QueryWrapper<>();
//                discussionQueryWrapper.eq("id",id).select("like_num");
//                Discussion discussion = discussionMapper.selectOne(discussionQueryWrapper);
//                if(Objects.nonNull(discussion)){
//                    cacheObject=String.valueOf(discussion.getLikeNum());
//                    redisCaches.setCacheObject(discusssLikekey,cacheObject);
//                }else {
//                    return false;
//                }
//            }
            QueryWrapper<DiscussionLike> queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("uid",loginUser.getId()).eq("did",id);
            DiscussionLike discussionLike = discussionLikeMapper.selectOne(queryWrapper);
            if(Objects.nonNull(discussionLike)){
                int deleteById = discussionLikeMapper.deleteById(discussionLike.getId());
                return deleteById > 0;
            }else {
                discussionLike=new DiscussionLike();
                discussionLike.setDid(id);
                discussionLike.setUid(loginUser.getId());
                int insert = discussionLikeMapper.insert(discussionLike);
                return insert>0;
            }
        }else {
            return false;
        }
    }

    @Override
    public List<Discussion> findList(Discussion discussion) {
        Wrapper<Discussion> wrapper = new QueryWrapper<>(discussion);
        return discussionMapper.selectList(wrapper);
    }
  
    @Override
    public PageData<Discussion> findPage(PageWrap<Discussion> pageWrap) {
        IPage<Discussion> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
        Discussion discussion = WrapperUtil.blankToNull(pageWrap.getModel());
        QueryWrapper<Discussion> queryWrapper = new QueryWrapper<>();
        for(PageWrap.SortData sortData: pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase("DESC")) {
                queryWrapper.orderByDesc(sortData.getProperty());
            } else {
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        if(Objects.nonNull(discussion.getTitle())){
            queryWrapper.like("title",discussion.getTitle());
        }
        if(Objects.nonNull(discussion.getCategoryId())){
            queryWrapper.eq("category_id",discussion.getCategoryId());
        }
        if(Objects.nonNull(discussion.getStatus())){
            queryWrapper.eq("status",discussion.getStatus());
        }
        queryWrapper.select("id","category_id","title","author","face_url","role","view_num","like_num","comment_num","status","create_time","update_time");
        return PageData.from(discussionMapper.selectPage(page, queryWrapper));
    }

    @Override
    public PageData<Discussion> findPageVo(PageWrap<Discussion> pageWrap) {
        LoginUser loginUser = redisCaches.getLoginUser();
        IPage<Discussion> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
        Discussion discussion = WrapperUtil.blankToNull(pageWrap.getModel());
        QueryWrapper<Discussion> queryWrapper = new QueryWrapper<>();
        for(PageWrap.SortData sortData: pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase("DESC")) {
                queryWrapper.orderByDesc(sortData.getProperty());
            } else {
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        if(Objects.nonNull(discussion.getCategoryId())&&discussion.getCategoryId()!=0){
            queryWrapper.eq("category_id",discussion.getCategoryId());
        }

        if(Objects.nonNull(discussion.getTitle())){
            queryWrapper.like("title",discussion.getTitle());
        }

        if(Objects.nonNull(discussion.getStatus())){
            queryWrapper.like("status",discussion.getStatus());
        }

        queryWrapper.select("id","category_id","title","description","pid","uid","author","face_url","role","view_num","like_num","comment_num","create_time");
        return PageData.from(discussionMapper.selectPage(page, queryWrapper));
    }

    @Override
    public Boolean reportDiscussion(DiscussionReportVO discussionReportVO) {
        if(Objects.nonNull(discussionReportVO)){
            LoginUser loginUser = redisCaches.getLoginUser();
            if(Objects.nonNull(discussionReportVO.getDid())&&Objects.nonNull(discussionReportVO.getContent())&&Objects.nonNull(loginUser.getId())){
                QueryWrapper<DiscussionReport> queryWrapper =new QueryWrapper<>();
                queryWrapper.eq("did",discussionReportVO.getDid()).eq("uid",loginUser.getId()).eq("status",0);
                Integer selectCount = discussionReportMapper.selectCount(queryWrapper);
                if(selectCount>0){
                    return false;
                }else {
                    DiscussionReport discussionReport = new DiscussionReport();
                    discussionReport.setReporter(loginUser.getUsername());
                    discussionReport.setDid(discussionReportVO.getDid());
                    discussionReport.setUid(loginUser.getId());
                    discussionReport.setContent(discussionReportVO.getContent());
                    discussionReport.setStatus(0);
                    int insert = discussionReportMapper.insert(discussionReport);
                    return insert>0;
                }
            }
        }
        return false;
    }

    @Override
    public List<CommentVO> getDiscussionCommentAndReplies(@NotNull DiscussionRequestVo discussionRequest) {
        QueryWrapper<Comment> queryWrapper=new QueryWrapper<>();
        if(Objects.nonNull(discussionRequest.getGid())&&discussionRequest.getGid()!=0){
            queryWrapper.eq("gid",discussionRequest.getGid());
        }else if(Objects.nonNull(discussionRequest.getTid())&&discussionRequest.getTid()!=0){
            queryWrapper.eq("tid",discussionRequest.getTid());
        }else if(Objects.nonNull(discussionRequest.getCid())&&discussionRequest.getCid()!=0){
            queryWrapper.eq("cid",discussionRequest.getCid());
        }else if(Objects.nonNull(discussionRequest.getDid())&&discussionRequest.getDid()!=0){
            queryWrapper.eq("did",discussionRequest.getDid());
        }
        List<Comment> commentList = commentMapper.selectList(queryWrapper);
        List<CommentVO> commentListVO=new ArrayList<>();
        if(Objects.nonNull(commentList)){
            for (Comment comment : commentList) {
                CommentVO commentVO = new CommentVO();
                commentVO.setCommentVoComment(comment);
                commentAndReplies(commentVO);
                commentListVO.add(commentVO);
            }
            return commentListVO;
        }
        return null;
    }


    public void commentAndReplies(CommentVO commentVO){

        if(Objects.nonNull(commentVO.getLevel())){
            QueryWrapper<Reply> replyQueryWrapper=new QueryWrapper<>();
            if(commentVO.getLevel()==0){
                replyQueryWrapper.eq("comment_id",commentVO.getId()).eq("level",1);
            }else{
                replyQueryWrapper.eq("reply_id",commentVO.getId()).eq("level",commentVO.getLevel()+1);
            }
            List<Reply> replies = replyMapper.selectList(replyQueryWrapper);
            if(Objects.isNull(replies)){
                return;
            }else {
                List<CommentVO> commentVOList=new ArrayList<>();
                for (Reply reply : replies) {
                    CommentVO commentVO1 = new CommentVO();
                    commentVO1.setCommentVoReply(reply);
                    commentVOList.add(commentVO1);
                }
                commentVO.setReplies(commentVOList);
                for (CommentVO vo : commentVOList) {
                    commentAndReplies(vo);
                }
            }
        }else {
            return;
        }

    }


    @Override
    public Boolean submitDiscussionComment(@NonNull SubDiscussionCommentVO subDiscussionCommentVO) {
        Comment comment = new Comment();
        if(Objects.nonNull(subDiscussionCommentVO.getGid())&&subDiscussionCommentVO.getGid()!=0){
            comment.setGid(subDiscussionCommentVO.getGid());
        }else if(Objects.nonNull(subDiscussionCommentVO.getTid())&&subDiscussionCommentVO.getTid()!=0){
            comment.setTid(subDiscussionCommentVO.getTid());
        }else if(Objects.nonNull(subDiscussionCommentVO.getCid())&&subDiscussionCommentVO.getCid()!=0){
            comment.setCid(subDiscussionCommentVO.getCid());
        }else if(Objects.nonNull(subDiscussionCommentVO.getDid())&&subDiscussionCommentVO.getDid()!=0){
            comment.setDid(subDiscussionCommentVO.getDid());
        }
        if(Objects.isNull(subDiscussionCommentVO.getContent())){
            return false;
        }else {
            LoginUser loginUser = redisCaches.getLoginUser();
            User user = userMapper.selectById(loginUser.getId());
            comment.setLevel(0);
            comment.setFromAvatar(user.getFaceUrl());
            comment.setFromUid(loginUser.getId());
            comment.setFromName(user.getUsername());
            comment.setFromRole(loginUser.getPermission().get(0));
            comment.setContent(subDiscussionCommentVO.getContent());
            int insert = commentMapper.insert(comment);
            return insert>0;
        }
    }

    @Override
    public Boolean submitCommentReply(@NonNull CommentReplyVO commentReplyVO) {
        Reply reply=new Reply();
        LoginUser loginUser = redisCaches.getLoginUser();
        if(Objects.nonNull(loginUser)&& Objects.equals(loginUser.getId(), commentReplyVO.getFromUid())){
            reply.setDid(commentReplyVO.getDid());
            reply.setCid(commentReplyVO.getCid());
            reply.setGid(commentReplyVO.getGid());
            reply.setTid(commentReplyVO.getTid());
            reply.setLevel(commentReplyVO.getLevel());
            reply.setCommentId(commentReplyVO.getCommentId());
            reply.setReplyId(commentReplyVO.getReplyId());
            reply.setToAvatar(commentReplyVO.getToAvatar());
            reply.setToName(commentReplyVO.getToName());
            reply.setToUid(commentReplyVO.getToUid());
            reply.setContent(commentReplyVO.getContent());
            reply.setFromRole(loginUser.getPermission().get(0));
            reply.setFromAvatar(commentReplyVO.getFromAvatar());
            reply.setFromName(loginUser.getUsername());
            reply.setFromUid(loginUser.getId());
            int insert = replyMapper.insert(reply);
            return insert>0;
        }
        return false;
    }

    @Override
    public long count(Discussion discussion) {
        Wrapper<Discussion> wrapper = new QueryWrapper<>(discussion);
        return discussionMapper.selectCount(wrapper);
    }
}
